package contextx

import (
	"context"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"zuhao-seucre/internal/common/model"
	"zuhao-seucre/internal/consts"
	"zuhao-seucre/internal/service"
)

type sContextX struct {
}

func New() *sContextX {
	return &sContextX{}
}

func init() {
	service.RegisterContextX(New())
}

// Init 初始化上下文对象指针到上下文对象中，以便后续的请求流程中可以修改
func (s *sContextX) Init(r *ghttp.Request, customCtx *model.Context) {
	r.SetCtxVar(consts.ContextHTTPKey, customCtx)
}

// Get 获得上下文变量，如果没有设置，那么返回nil
func (s *sContextX) Get(ctx context.Context) *model.Context {
	value := ctx.Value(consts.ContextHTTPKey)
	if value == nil {
		return nil
	}
	if localCtx, ok := value.(*model.Context); ok {
		return localCtx
	}
	return nil
}

// SetUser 将上下文信息设置到上下文请求中，注意是完整覆盖
func (s *sContextX) SetUser(ctx context.Context, user *model.UserModel) {
	c := s.Get(ctx)
	if c == nil {
		g.Log().Warning(ctx, "contexts.SetUser, c == nil ")
		return
	}
	c.User = user
}

// SetResponse 设置组件响应 用于访问日志使用
func (s *sContextX) SetResponse(ctx context.Context, response *model.Response) {
	c := s.Get(ctx)
	if c == nil {
		g.Log().Warning(ctx, "contexts.SetResponse, c == nil ")
		return
	}
	c.Response = response
}

// GetUser 获取用户信息
func (s *sContextX) GetUser(ctx context.Context) *model.UserModel {
	c := s.Get(ctx)
	if c == nil {
		return nil
	}
	return c.User
}

// GetUserId 获取用户ID
func (s *sContextX) GetUserId(ctx context.Context) uint64 {
	user := s.GetUser(ctx)
	if user == nil {
		return 0
	}
	return user.UserId
}

// SetData 设置额外数据
func (s *sContextX) SetData(ctx context.Context, k string, v interface{}) {
	c := s.Get(ctx)
	if c == nil {
		g.Log().Warning(ctx, "contexts.SetData, c == nil ")
		return
	}
	s.Get(ctx).Data[k] = v
}

// SetDataMap 设置额外数据
func (s *sContextX) SetDataMap(ctx context.Context, vs g.Map) {
	c := s.Get(ctx)
	if c == nil {
		g.Log().Warning(ctx, "contexts.SetData, c == nil ")
		return
	}

	for k, v := range vs {
		s.Get(ctx).Data[k] = v
	}
}

// GetData 获取额外数据
func (s *sContextX) GetData(ctx context.Context) g.Map {
	c := s.Get(ctx)
	if c == nil {
		return nil
	}
	return c.Data
}
